/*********************************************************************
* File: Senses.h
*
* Implements the vision and hearing API.
*********************************************************************/
#pragma once

namespace agents{ class Agent; }
#include "../../engine.h"
#include "../globals.h"
#include "../../game/globals.h"
#include "../interfaces/IVision.h"
#include "../interfaces/IHearing.h"
#include "../interfaces/IRadar.h"
using namespace agents::interfaces;

namespace agents{ namespace modules{
	/**
	* \brief Implements the vision and hearing API.
	* 
	* Supports seeing enemies, teammates and objects as well as hearing things 
	* in the world.
	*
	* \author Instituto Superior Tecnico de Lisboa, Portugal
	* \author Technical University of Lisbon, Portugal
	* 
	* \author Agentes Autonomos e Sistemas Multiagente
	* \author Autonomous Agents and Multiagent Systems
	* 
	* \version	1.0
	* \date		2006/2007
	**/
	class Senses: public IVision, public IHearing, public IRadar{
	public:
		//=====================================================================
		// Function prototypes
		//=====================================================================
		Senses(Agent &owner);
		~Senses();

		void newRound();

		float getFieldOfView();
		bool isPointVisible(Vector point);
		IVisibleAgent** seeTeammates(int* count);
		IVisibleAgent** seeEnemies(int* count);
		void seeWeaponsOnTheFloor(PickableWeapon* weapons, int* count);
		
		bool isArmedBombVisible(Vector* position);
		bool isDroppedBombVisible(Vector* position);
		bool isBomberVisible(IVisibleAgent* bomber);
		bool inflictedDamage(IVisibleAgent* shooter);
		
		bool isHeGrenadeVisible(Vector* position);
		bool isSmokeGrenadeVisible(Vector* position);
		bool isFlashbangVisible(Vector* position);

		int getAngleInFieldOfView(Vector dest);
		bool hearsBomb(Vector* direction);

		RadarUnit* getRadarVisibleUnits(int* count);

	protected:
		bool agentIsVisible(edict_t* agent);
		bool agentBodyPartIsVisible(edict_t* agent, BodyPart::Enumeration bodyPart, Vector* bodyPartPosition = NULL);
		bool inViewCone(Vector point);
		bool isGrenadeVisible(const char* grenadeModelName, Vector* position = NULL);

		/** 
		* \brief The agent.
		**/
		Agent &_owner;

	private:
		void updateSeenBots();

		/** 
		* \brief Visible teammates.
		**/
		IVisibleAgent** _visibleTeammates;
		/** 
		* \brief Visible enemies.
		**/
		IVisibleAgent** _visibleEnemies;
		/** 
		* \brief Visible radar units.
		**/
		RadarUnit* _visibleRadarUnits;
		/** 
		* \brief Visible teammates count.
		**/
		int _teammatesCount;
		/** 
		* \brief Visible enemies count.
		**/
		int _enemiesCount;
	};

	class VisibleAgent: public IVision::IVisibleAgent
	{
	public:
		/** 
		* \brief Class constructor.
		**/
		VisibleAgent(){ _canSeeHealth=false; _entity=NULL; }

		void setAgent(edict_t* agent, bool isSameTeam);
		/** 
		* \brief Gets the agent entity.
		**/
		edict_t* getAgent(){ return _entity; }
		const char* getName();
		CounterStrikeTeams::Enumeration getTeam();
		Vector getPosition();
		Vector getBodyPartPosition(BodyPart::Enumeration bodyPart);
		WeaponIds::Enumeration getPrimaryWeapon();
		WeaponIds::Enumeration getSecondaryWeapon();
		bool isHumanPlayer();
		int getHealth();

	private:
		bool _canSeeHealth;
		edict_t* _entity;
		char _name[AGENT_NAME_MAX_LENGTH];
	};
}}
